﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Data.SQLite;
using System.Data;
using SegIdenMovilBT.Herramientas;

namespace SegIdenMovilBT.DataAccess
{
    public class Database : IDisposable
    {
        #region --- Variable Privadas ---
        private SQLiteConnection conexion = null;
        private SQLiteCommand comando = null;
        private SQLiteDataAdapter adap = null;

        private const string FORMATO_CADENA_CONEXION = "Data Source={0};New={1};Compress=False;Version={2}";
        private const string FORMATO_ERROR_SCRIPT = "Error:{0} \r\n Script: {1} \r\n ¿Desea Continuar?";
        #endregion

        #region --- Constructor y Destructor ---
        public Database()
        {
        }

        private bool disposedValue = false; // Para detectar llamadas redundantes
        // IDisposable
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    if (this.conexion != null)
                    {
                        if (this.conexion.State == ConnectionState.Open) this.conexion.Close();
                        this.conexion.Dispose();
                    }
                    this.conexion = null;
                }
            }
            this.disposedValue = true;
        }

        public void Dispose()
        {
            // No cambie este código. Coloque el código de limpieza en Dispose (ByVal que se dispone como Boolean).
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        #region --- Metodos Conexion ---
        /// <summary>
        /// Metodo: Que permite aperturar la conexion a la Base de Datos
        /// </summary>
        /// <returns></returns>
        public SQLiteConnection abrir()
        {
            if (this.conexion == null)
            {
                this.conexion = new SQLiteConnection(string.Format(FORMATO_CADENA_CONEXION, Constantes.STR_RUTABASEDATOS, false, 3));
            }

            if (this.conexion.State == ConnectionState.Closed) this.conexion.Open();
            return this.conexion;
        }

        /// <summary>
        /// Metodo: Que permite cerra la conexion a la Base de Datos
        /// </summary>
        /// <returns></returns>
        public void cerrar()
        {
            this.conexion.Close();
        }
        #endregion

        #region --- Metodos Transaccion ---
        public IDbTransaction iniciarTransaccionSQLite()
        {
            return this.abrir().BeginTransaction();
        }

        public void iniciarTransaccion()
        {
            if (this.comando == null)
            {
                this.comando = new SQLiteCommand();
            }

            if (this.conexion == null)
            {
                this.abrir();
            }

            this.comando.Connection = this.conexion;
            this.comando.CommandType = CommandType.Text;
            this.comando.CommandText = string.Empty;
            this.comando.Connection.BeginTransaction();
        }

        public void confirmarTransaccion()
        {
            if (this.comando != null)
            {
                this.comando.Transaction.Commit();
            }
        }
        #endregion

        #region --- Propiedades y Metodos Propios ---
        public string TextoSQL
        {
            set
            {
                if (this.comando == null)
                {
                    this.comando = new SQLiteCommand();
                }

                if (this.conexion == null) { this.abrir(); }

                this.comando.Connection = this.conexion;
                this.comando.CommandType = CommandType.Text;
                this.comando.CommandText = value;
                this.comando.Parameters.Clear();
            }
        }

        public string NombreProcedimiento
        {
            set
            {
                if (this.comando == null)
                {
                    this.comando = new SQLiteCommand();
                }

                if (this.conexion == null) { this.abrir(); }

                this.comando.Connection = this.conexion;
                this.comando.CommandType = CommandType.StoredProcedure;
                this.comando.CommandText = value;
                this.comando.Parameters.Clear();
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro)
        {
            if (this.comando != null)
            {
                SQLiteParameter parametro = new SQLiteParameter();
                parametro.ParameterName = nombreParametro;
                parametro.DbType = tipoParametro;
                parametro.Direction = direccionParametro;

                this.comando.Parameters.Add(parametro);
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro, Object valorParametro)
        {
            if (comando != null)
            {
                SQLiteParameter parametro = new SQLiteParameter();
                parametro.ParameterName = nombreParametro;

                parametro.DbType = tipoParametro;

                parametro.Direction = direccionParametro;
                parametro.Value = valorParametro;

                this.comando.Parameters.Add(parametro);
            }
        }

        public void agregarParametro(string nombreParametro, DbType tipoParametro, ParameterDirection direccionParametro, Object valorParametro, int tamanioParametro)
        {
            if (comando != null)
            {
                SQLiteParameter parametro = new SQLiteParameter();
                parametro.ParameterName = nombreParametro;
                parametro.DbType = tipoParametro;
                parametro.Direction = direccionParametro;
                parametro.Value = valorParametro;
                parametro.Size = tamanioParametro;

                this.comando.Parameters.Add(parametro);
            }
        }

        public IDataParameter obtenerParametro(string nombreParametro)
        {
            if (comando != null)
            {
                return comando.Parameters[nombreParametro];
            }
            return null;
        }

        public IDataReader obtenerDataReader()
        {
            return this.comando.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection);
        }

        public IDataAdapter obtenerDataAdapter()
        {
            if (this.adap == null)
            {
                this.adap = new SQLiteDataAdapter();
            }

            if (this.conexion == null) { this.abrir(); }

            this.adap.SelectCommand = this.comando;

            return adap;
        }

        public int ejecutar()
        {
            return this.comando.ExecuteNonQuery();
        }

        public object ejecutarEscalar()
        {
            return this.comando.ExecuteScalar();
        }
        #endregion
    }
}
